package com.hsy.crm.web.service.impl;

import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.hsy.crm.web.domain.cm.App;
import com.hsy.crm.web.domain.cm.PageResult;
import com.hsy.crm.web.domain.cm.Unified;
import com.hsy.crm.web.domain.entity.StoneOther;
import com.hsy.crm.web.domain.entity.StoneOtherDetail;
import com.hsy.crm.web.domain.entity.StoreProduct;
import com.hsy.crm.web.domain.ex.ServiceException;
import com.hsy.crm.web.domain.po.stoneOther.StoneOtherGetPo;
import com.hsy.crm.web.domain.po.stoneOther.StoneOtherPagePo;
import com.hsy.crm.web.domain.vo.stoneOther.StoneOtherPageVo;
import com.hsy.crm.web.domain.vo.stoneOther.StoneOtherVo;
import com.hsy.crm.web.mapper.StoneOtherDetailMapper;
import com.hsy.crm.web.mapper.StoneOtherMapper;
import com.hsy.crm.web.service.base.BaseService;
import com.hsy.crm.web.service.base.CacheService;
import com.hsy.crm.web.service.base.DataInitService;
import com.hsy.crm.web.utils.CalcUtils;
import com.hsy.crm.web.utils.ServiceUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;

@Service
public class StoneOtherService extends BaseService<StoneOther> {

    @Autowired
    StoneOtherMapper stoneOtherMapper;

    @Autowired
    StoneOtherDetailMapper stoneOtherDetailMapper;

    @Autowired
    MessageService messageService;

    @Autowired
    StoreProductService storeProductService;

    @Transactional
    public Unified<StoneOther> insertStoneOther(StoneOtherVo stoneOtherVo) {
        Unified<StoneOther> unified = new Unified<>();

        StoneOther stoneOther = stoneOtherVo.getStoneOther();
        stoneOther.setCode(DataInitService.getOrderCode());
        stoneOther.setStatus(App.Status.BC);

        if( stoneOther.getOtherType() == 1 ){
            stoneOther.setOrderType(App.BILL_TYPE.ORDER_QTRKD);
        }else{
            stoneOther.setOrderType(App.BILL_TYPE.ORDER_QTCKD);
        }

        stoneOther.setLoginUserId(stoneOtherVo.getLoginUserId());
        stoneOther.setCustomerId(stoneOtherVo.getCustomerId());
        stoneOther.setLoginCompanyId(stoneOtherVo.getLoginCompanyId());
        this.insert(stoneOther);
        this.insertDetails(stoneOtherVo);

        if( stoneOtherVo.getSaveType() == App.SaveType.EXAMINE ){
            this.examine(stoneOtherVo);
        }
        unified.setData(stoneOther);
        return unified;
    }

    @Transactional
    public Unified<Integer> examine(StoneOtherVo vo) {
        StoneOther stoneOther = vo.getStoneOther();
        stoneOther.setCustomerId(vo.getCustomerId());
        Unified<Integer> unified = new Unified<>();
        // update status
        StoneOther updateStoneOther = this.getUpdateStoneOther(stoneOther,App.Status.SH);
        this.update(updateStoneOther);

        update_store_product_exam(vo);

        messageService.addMessage(stoneOther,vo.getDetails(),App.ExamType.EXAMINE);
        return unified;
    }

    @Transactional
    public Unified<Integer> invalid(StoneOther stoneOther) {
        Unified<Integer> unified = new Unified<>();
        stoneOther = this.getStoneOther(stoneOther);

        // update status
        StoneOther updateStoneOther = this.getUpdateStoneOther(stoneOther,App.Status.BC);
        this.update(updateStoneOther);

        List<StoneOtherDetail> orderDetails = this.getOrderDetails(stoneOther);
        update_store_product_invalid(orderDetails,stoneOther);
        messageService.addMessage(stoneOther,orderDetails,App.ExamType.INVALID);

        return unified;
    }

    @Transactional
    public Unified<Integer> deleteStoneOther(StoneOther stoneOther) {
        this.deleteDetails(stoneOther);
        return Unified.newInstance(this.delete(stoneOther));
    }

    public PageResult<StoneOtherPagePo> page(StoneOtherPageVo stoneOtherPageVo) {
        Page page = PageHelper.startPage(stoneOtherPageVo.getPage(),stoneOtherPageVo.getLimit());
        PageResult<StoneOtherPagePo> pageResult = new PageResult<>();
        pageResult.setRows(stoneOtherMapper.page(stoneOtherPageVo));
        pageResult.setTotal(page.getTotal());
        return pageResult;
    }

    @Transactional
    public Unified<StoneOther> updateStoneOther(StoneOtherVo stoneOtherVo) {
        Unified<StoneOther> unified = new Unified<>();

        StoneOther stoneOther = stoneOtherVo.getStoneOther();
        stoneOther.setLoginUserId(stoneOtherVo.getLoginUserId());
        stoneOther.setOrderType(App.BILL_TYPE.ORDER_QTRKD);
        stoneOther.setCustomerId(stoneOtherVo.getCustomerId());
        stoneOther.setLoginCompanyId(stoneOtherVo.getLoginCompanyId());

        this.update(stoneOther);
        this.deleteDetails(stoneOther);
        this.insertDetails(stoneOtherVo);

        if( stoneOtherVo.getSaveType() == App.SaveType.EXAMINE ){
            this.examine(stoneOtherVo);
        }
        unified.setData(stoneOther);

        return unified;
    }

    @Transactional
    public Unified<StoneOtherGetPo> getOrder(StoneOther stoneOther) {
        Unified<StoneOtherGetPo> unified = new Unified<>();
        StoneOtherGetPo resultPo = new StoneOtherGetPo();
        resultPo.setStoneOther(stoneOtherMapper.selectByPrimaryKey(stoneOther));
        resultPo.setDetails(stoneOtherMapper.getOrder(stoneOther));
        unified.setData(resultPo);
        return unified;
    }

    private void update_store_product_exam(StoneOtherVo vo){
        Integer orderType = App.BILL_TYPE.ORDER_QTRKD;
        for( StoneOtherDetail detail : vo.getDetails() ){
            StoreProduct storeProduct = getStoreProduct(vo.getCustomerId(),orderType,vo.getStoneOther().getCompanyId(),detail);
            storeProduct.setPrice(getPrice(detail));
            storeProductService.update(storeProduct,vo.getStoneOther().getOtherType());
            detail.setStoreProductId(storeProduct.getId());
        }
    }

    private void update_store_product_invalid(List<StoneOtherDetail> details,StoneOther other){
        int direction = other.getOtherType() == 1 ? App.StoreType.IN : App.StoreType.OUT;
        Integer orderType = App.BILL_TYPE.ORDER_QTRKD;
        for( StoneOtherDetail detail : details ){
            StoreProduct storeProduct = getStoreProduct(other.getCustomerId(),orderType,other.getCompanyId(),detail);
            storeProduct.setPrice(getPrice(detail));
            storeProductService.update(storeProduct,direction);
        }
    }

    public static Long getPrice(StoneOtherDetail orderDetail){
        double totalPrice = CalcUtils.mul(orderDetail.getNumber(),orderDetail.getPrice());
        totalPrice = CalcUtils.div(totalPrice,App.DECIMAL.DIV);
        return ((Double)totalPrice).longValue();
    }

    private static StoreProduct getStoreProduct(String customerId,Integer orderType,Long companyId,StoneOtherDetail orderDetail){
        StoreProduct storeProduct = new StoreProduct();
        storeProduct.setCompanyId(companyId);
        storeProduct.setProductId(orderDetail.getProductId());
        storeProduct.setStoreId(orderDetail.getStoreId());
        storeProduct.setUnitId(orderDetail.getUnitId());
        storeProduct.setCustomerId(customerId);
        storeProduct.setNumber(orderDetail.getNumber());

        return storeProduct;
    }

    private List<StoneOtherDetail> getOrderDetails(StoneOther order){
        StoneOtherDetail orderDetail = new StoneOtherDetail();
        orderDetail.setStoneOtherId(order.getId());
        orderDetail.setCustomerId(order.getCustomerId());
        return stoneOtherDetailMapper.select(orderDetail);
    }

    private void insertDetails(StoneOtherVo stoneOtherVo){
        Long stoneOtherId = stoneOtherVo.getStoneOther().getId();
        for(StoneOtherDetail detail : stoneOtherVo.getDetails()){

            if( !CacheService.hasProductId(stoneOtherVo.getCustomerId(),detail.getProductId())){
                throw new ServiceException(detail.getProductId());
            }

            detail.setCustomerId(stoneOtherVo.getCustomerId());
            detail.setStoneOtherId(stoneOtherId);
            ServiceUtils.init_entity_insert(detail);
            stoneOtherDetailMapper.insert(detail);
        }
    }

    private void deleteDetails(StoneOther stoneOther){
        StoneOtherDetail stoneOtherDetail = new StoneOtherDetail();
        stoneOtherDetail.setCustomerId(stoneOther.getCustomerId());
        stoneOtherDetail.setStoneOtherId(stoneOther.getId());
        stoneOtherDetailMapper.delete(stoneOtherDetail);
    }

    private StoneOther getUpdateStoneOther(StoneOther stoneOther,int status){
        StoneOther updateStoneOther = new StoneOther();
        stoneOther.setCompanyId(stoneOther.getLoginCompanyId());
        updateStoneOther.setId(stoneOther.getId());
        updateStoneOther.setCustomerId(stoneOther.getCustomerId());
        updateStoneOther.setStatus(status);
        updateStoneOther.setLoginUserId(stoneOther.getLoginUserId());
        return updateStoneOther;
    }

    private StoneOther getStoneOther(StoneOther stoneOther){
        StoneOther select = new StoneOther();
        select.setCustomerId(stoneOther.getCustomerId());
        select.setId(stoneOther.getId());
        select = stoneOtherMapper.selectByPrimaryKey(select);
        select.setCustomerId(stoneOther.getCustomerId());
        select.setLoginCompanyId(stoneOther.getLoginCompanyId());
        select.setLoginCompanyLogicalCode(stoneOther.getLoginCompanyLogicalCode());
        select.setLoginUserId(stoneOther.getLoginUserId());
        return select;
    }

}
